import os
import re
from typing import Any, Dict, List

from oneconvert.datasource.base import BaseDataSource


def to_json(flat_data: Dict[str, str]) -> Dict[str, Any]:
    result: Dict[str, Any] = {}
    list_index_pattern = re.compile(r'^(.+)\[(\d+)]$')  # 匹配列表格式 key[index]

    for key, value in flat_data.items():
        current = result
        parts = key.split('.')  # 按点号分割层级

        for i, part in enumerate(parts):
            # 检查是否为列表项（如 "features[0]"）
            list_match = list_index_pattern.match(part)
            if list_match:
                # 提取列表名和索引
                list_name = list_match.group(1)
                index = int(list_match.group(2))

                # 确保列表容器存在
                if list_name not in current:
                    current[list_name] = []

                # 如果是最后一部分，处理值
                if i == len(parts) - 1:
                    # 扩展列表到所需长度
                    while len(current[list_name]) <= index:
                        current[list_name].append(None)
                    current[list_name][index] = _convert_value(value)
                else:
                    # 处理嵌套在列表中的结构
                    while len(current[list_name]) <= index:
                        current[list_name].append({})
                    current = current[list_name][index]
            else:
                # 处理普通键
                if i == len(parts) - 1:
                    # 最后一部分，设置值
                    current[part] = _convert_value(value)
                else:
                    # 非最后一部分，确保字典存在
                    if part not in current:
                        current[part] = {}
                    current = current[part]

    return result


def _convert_value(value: str) -> Any:
    """将字符串值转换为合适的Python类型"""
    # 处理布尔值
    if value.lower() == 'true':
        return True
    if value.lower() == 'false':
        return False

    # 处理空值
    if value == '':
        return None

    # 处理数字
    try:
        # 尝试转换为整数
        return int(value)
    except ValueError:
        try:
            # 尝试转换为浮点数
            return float(value)
        except ValueError:
            # 保留原始字符串
            return value


def from_json(data: Any, parent_key: str = '', sep: str = '.') -> Dict[str, str]:
    items: List[tuple] = []

    # 处理字典类型
    if isinstance(data, dict):
        for k, v in data.items():
            new_key = f"{parent_key}{sep}{k}" if parent_key else k
            items.extend(from_json(v, new_key, sep=sep).items())

    # 处理列表类型
    elif isinstance(data, list):
        for i, v in enumerate(data):
            new_key = f"{parent_key}[{i}]" if parent_key else f"[{i}]"
            items.extend(from_json(v, new_key, sep=sep).items())

    # 处理基本类型
    else:
        # 将值转换为字符串，处理None值
        str_value = str(data) if data is not None else ''
        items.append((parent_key, str_value))

    return dict(items)


class PropertiesDataSource(BaseDataSource):
    def read(self, encoding='utf-8', **kwargs):
        if not os.path.isfile(self.uri):
            raise ValueError(f'the file {self.uri} not found')

        flat_data: Dict[str, str] = {}
        with open(self.uri, 'r', encoding=encoding) as f:
            for line_num, line in enumerate(f, 1):
                line = line.strip()
                # 跳过空行和注释
                if not line or line.startswith(('#', '!')):
                    continue

                # 分割键值对（处理转义的等号和冒号）
                separator_index = -1
                for i, c in enumerate(line):
                    if c in ('=', ':') and (i == 0 or line[i - 1] != '\\'):
                        separator_index = i
                        break

                if separator_index == -1:
                    # 没有分隔符，视为键且值为空
                    key = line
                    value = ''
                else:
                    key = line[:separator_index].strip()
                    value = line[separator_index + 1:].strip()

                # 还原转义的特殊字符
                key = key.replace('\\=', '=').replace('\\:', ':')
                value = value.replace('\\=', '=').replace('\\:', ':')

                flat_data[key] = value

        return to_json(flat_data)

    def write(self, data, encoding='utf-8', **kwargs):
        flattened_data = from_json(data)

        dir_name = os.path.dirname(self.uri)
        if dir_name and not os.path.exists(dir_name):
            os.makedirs(dir_name, exist_ok=True)

        with open(self.uri, 'w', encoding=encoding) as f:
            for key, value in flattened_data.items():
                # 处理值中的等号和冒号，避免解析问题
                escaped_value = value.replace('=', '\\=').replace(':', '\\:')
                f.write(f"{key}={escaped_value}\n")
